﻿using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using LinFu.IoC;
using LinFu.IoC.Configuration;

namespace CoreEx.ServiceModel.Implementation
{
    /// <summary>
    /// A custom <see cref="IServiceBehavior"/> that 
    /// adds all registered <see cref="IErrorHandler"/> implementations .
    /// </summary>
    /// <example>
    /// The following example shows how to implement an error handler that 
    /// forwards error messages to the console output window.
    /// <code>
    /// <![CDATA[
    ///    [Implements(typeof(IErrorHandler),ServiceName = "SampleErrorHandler")]
    ///    public class SampleErrorHandler : IErrorHandler
    ///    {        
    ///        public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
    ///        {
    ///            //Do nothing here.    
    ///        }
    ///        
    ///        public bool HandleError(Exception error)
    ///        {
    ///            Console.WriteLine(error);
    ///            return false;
    ///        }
    ///    }
    /// ]]>
    /// </code>
    /// </example>
    [Implements(typeof(IServiceBehavior), ServiceName = "ErrorHandlerServiceBehavior")]
    public class ErrorHandlerServiceBehavior : ServiceBehaviorBase
    {
        /// <summary>
        /// Adds all registered <see cref="IErrorHandler"/> implementations to 
        /// the <see cref="ChannelDispatcher.ErrorHandlers"/> collection.
        /// </summary>
        /// <param name="serviceDescription">The service description.</param>
        /// <param name="serviceHostBase">The host that is currently being built.</param>
        public override void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            var errorHandlers = ServiceContainer.GetServices<IErrorHandler>();

            if (errorHandlers.Count() == 0)
                return;
            foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
            {
                foreach (var errorHandler in errorHandlers)
                {                                        
                    dispatcher.ErrorHandlers.Add(errorHandler);
                }
            }
        }        
    }
}
